import { Rect, v2, v3, Vec2, Vec3 } from "cc";
import { RandomUtils } from "./RandomUtils";

export default class MathUtils {

    /**根据角度计算弧度 */
    static getRadiansByAngle(angle: number) {
        return angle * 180 / Math.PI;
    }

    /**
     * 根据坐标计算角度
     */
    static getAngleByXY(x1, y1, x2 = 0, y2 = 1) {
        return Math.atan2(y1, x1) - Math.atan2(y2, x2)
    }

    /**
     * 计算两个向量平面弧度(相对于v2向量的位置)
     */
    static getRadinsByXY(x1, y1, x2 = 0, y2 = 1) {
        return this.getRadiansByAngle(this.getAngleByXY(x1, y1, x2, y2))
    }

    static getVectorByAngle(angle) {
        if (angle === 0) {
            return v2(0, 1);
        }
        if (angle === 90) {
            return v2(-1, 0);
        }
        if (angle === 180) {
            return v2(0, -1);
        }
        if (angle === 270) {
            return v2(1, 0);
        }
        let x = -Math.sin(angle * Math.PI / 180);
        let y = Math.cos(angle * Math.PI / 180);
        return v2(x, y);
    }
    /**旋转向量 */
    static rotateVectorByRadians(x, y, radians): Vec2 {
        let newX = x * Math.cos(radians) - y * Math.sin(radians)
        let newY = y * Math.cos(radians) + x * Math.sin(radians)
        return v2(newX, newY)
    }

    static getMapLength(map: any) {
        let length = 0
        for (const key in map) {
            length++
        }
        return length
    }

    /**根据世界坐标,半径,数量,生成一个以worldPos为中心,distance为半径的圆上的坐标数组, */
    static genPositionByCount(worldPos: Vec3, distance: number, count: number): Vec3[] {
        let arrPos: Vec3[] = []
        for (let i = 0; i < count; i++) {
            const angle = 360 / count * i;
            const x = worldPos.x + distance * (Math.cos(angle * Math.PI / 180));
            const y = worldPos.y + distance * (Math.sin(angle * Math.PI / 180));
            arrPos[arrPos.length] = v3(x, y, 0);
        }
        return arrPos;
    }

    /**根据世界坐标,半径,数量,生成一个以worldPos为中心,distance为半径的圆内的坐标数组, */
    static genPositionByCountInCircle(worldPos: Vec3, distance: number, count: number): Vec3[] {
        let arrPos: Vec3[] = []
        for (let i = 0; i < count; i++) {
            const angle = 360 / count * i;
            const randomDis: number = RandomUtils.range(0, 1);
            const x = worldPos.x + distance * randomDis * (Math.cos(angle * Math.PI / 180));
            const y = worldPos.y + distance * randomDis * (Math.sin(angle * Math.PI / 180));
            arrPos[arrPos.length] = v3(x, y, 0)
        }
        return arrPos;
    }
    /** 
     * 判断点在向量的哪一侧
     * @property worldPos:要判断的点
     * @property vPstart:向量起点
     * @property vPend:向量终点
     * @returns res: > 0 左侧 res: < 0 右侧 res : = 0 在向量上
     */
    static checkPosOnVectorPlace(worldPos: Vec2, vPstart: Vec2, vPend: Vec2): number {
        let res = (vPend.x - vPstart.x) * (worldPos.y - vPstart.y) - (vPend.y - vPstart.y) * (worldPos.x - vPstart.x)
        return res
    }

    /**在rect范围内随机一个点 */
    static getRandomPosInRect(rect: Rect): Vec3 {
        let xMin = rect.x
        let xMax = rect.width + rect.x
        let yMin = rect.y
        let yMax = rect.height + rect.y
        let x = RandomUtils.rangeInt(xMax, xMin)
        let y = RandomUtils.rangeInt(yMax, yMin)
        return v3(x, y, 0)
    }

    /**在rect里生成格子中心点集合 */
    static getPositionsInRect(rect: Rect, cellWidth: number, cellHeight?: number): Vec2[] {
        if (!cellHeight) {
            cellHeight = cellWidth
        }
        let posList: Vec2[] = []
        let x = rect.xMin + cellWidth * 0.5
        let y = rect.yMax - cellHeight * 0.5
        while (y > rect.yMin + cellHeight * 0.5) {
            let pos = v2(x, y)
            x += cellWidth
            if (x > rect.xMax - cellWidth * 0.5) {
                //换行
                x = rect.xMin + cellWidth * 0.5
                y -= cellHeight
            }
            posList.push(pos)
        }
        return posList
    }

    /**计算两个position之间距离 */
    static getPosDis(worldPos1: Vec3, worldPos2: Vec3): number {
        return worldPos1.subtract(worldPos2).length()
    }
    /**计算两个position之间距离平方,用于比较大小 */
    static getPosDisSqr(worldPos1: Vec3, worldPos2: Vec3): number {
        return worldPos1.subtract(worldPos2).lengthSqr()
    }
    /**检查坐标是否相等 */
    static checkSamePos(pos1: Vec3, pos2: Vec3): boolean {
        return pos1.x == pos2.x && pos2.y == pos2.y
    }

    /**检查世界坐标是否在框内 */
    static checkWorldPosInCanvas(pos: Vec3, rect: Rect): boolean {
        let xMin = rect.x
        let xMax = rect.width - rect.x
        let yMin = rect.y
        let yMax = rect.height - rect.y
        if (pos.x >= xMin && pos.x <= xMax && pos.y >= yMin && pos.y <= yMax) {
            return true
        }
        return false
    }

    /**
     * 插值运算
     * @param a 初始值
     * @param b 目标值
     * @param t 间隔比例
     * @returns 
     */
    static lerp(a: number, b: number, t: number) {
        return a + (b - a) * t;
    }
}